package com.iot.processor.parser;

import com.iot.processor.model.SensorData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * 消息解析器
 * 负责将十六进制字符串解析为SensorData对象
 * 
 * 协议格式：
 * 前8位: 设备ID (Hex)
 * 后8位: 系统时间戳 (Hex)
 * 再4位: 温度 (Hex)，值为真实温度的100倍
 * 最后4位: 湿度 (Hex)，值为真实湿度的100倍
 * 
 * 示例: 0000000161C0A5F009F6177F
 */
public class MessageParser {
    
    private static final Logger logger = LoggerFactory.getLogger(MessageParser.class);
    
    // 协议字段长度定义
    private static final int DEVICE_ID_LENGTH = 8;
    private static final int TIMESTAMP_LENGTH = 8;
    private static final int TEMPERATURE_LENGTH = 4;
    private static final int HUMIDITY_LENGTH = 4;
    private static final int TOTAL_MESSAGE_LENGTH = DEVICE_ID_LENGTH + TIMESTAMP_LENGTH + 
                                                   TEMPERATURE_LENGTH + HUMIDITY_LENGTH;
    
    /**
     * 解析十六进制消息为传感器数据对象
     * 
     * @param hexMessage 十六进制消息字符串
     * @return 解析后的传感器数据对象
     * @throws IllegalArgumentException 当消息格式不正确时抛出
     */
    public SensorData parseMessage(String hexMessage) {
        if (hexMessage == null || hexMessage.trim().isEmpty()) {
            throw new IllegalArgumentException("消息不能为空");
        }
        
        // 移除可能的空格和转换为大写
        hexMessage = hexMessage.trim().toUpperCase();
        
        // 验证消息长度
        if (hexMessage.length() != TOTAL_MESSAGE_LENGTH) {
            throw new IllegalArgumentException(
                String.format("消息长度不正确，期望 %d 位，实际 %d 位: %s", 
                    TOTAL_MESSAGE_LENGTH, hexMessage.length(), hexMessage));
        }
        
        // 验证是否为有效的十六进制字符串
        if (!hexMessage.matches("[0-9A-F]+")) {
            throw new IllegalArgumentException("消息包含非十六进制字符: " + hexMessage);
        }
        
        try {
            // 解析各个字段
            String deviceIdHex = hexMessage.substring(0, DEVICE_ID_LENGTH);
            String timestampHex = hexMessage.substring(DEVICE_ID_LENGTH, DEVICE_ID_LENGTH + TIMESTAMP_LENGTH);
            String temperatureHex = hexMessage.substring(DEVICE_ID_LENGTH + TIMESTAMP_LENGTH, 
                                                       DEVICE_ID_LENGTH + TIMESTAMP_LENGTH + TEMPERATURE_LENGTH);
            String humidityHex = hexMessage.substring(DEVICE_ID_LENGTH + TIMESTAMP_LENGTH + TEMPERATURE_LENGTH);
            
            // 转换为实际值
            String deviceId = parseDeviceId(deviceIdHex);
            LocalDateTime timestamp = parseTimestamp(timestampHex);
            Double temperature = parseTemperature(temperatureHex);
            Double humidity = parseHumidity(humidityHex);
            
            logger.debug("解析消息成功: deviceId={}, timestamp={}, temperature={}, humidity={}", 
                        deviceId, timestamp, temperature, humidity);
            
            return new SensorData(deviceId, timestamp, temperature, humidity, hexMessage);
            
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("解析十六进制数值失败: " + hexMessage, e);
        } catch (Exception e) {
            throw new IllegalArgumentException("解析消息时发生未知错误: " + hexMessage, e);
        }
    }
    
    /**
     * 解析设备ID
     */
    private String parseDeviceId(String deviceIdHex) {
        long deviceIdLong = Long.parseUnsignedLong(deviceIdHex, 16);
        return String.format("DEVICE_%08d", deviceIdLong);
    }
    
    /**
     * 解析时间戳
     */
    private LocalDateTime parseTimestamp(String timestampHex) {
        long timestampLong = Long.parseUnsignedLong(timestampHex, 16);
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestampLong), ZoneId.systemDefault());
    }
    
    /**
     * 解析温度（除以100得到实际温度）
     */
    private Double parseTemperature(String temperatureHex) {
        int temperatureInt = Integer.parseUnsignedInt(temperatureHex, 16);
        return temperatureInt / 100.0;
    }
    
    /**
     * 解析湿度（除以100得到实际湿度）
     */
    private Double parseHumidity(String humidityHex) {
        int humidityInt = Integer.parseUnsignedInt(humidityHex, 16);
        return humidityInt / 100.0;
    }
    
    /**
     * 验证解析结果的合理性
     */
    public boolean validateSensorData(SensorData data) {
        if (data == null) {
            return false;
        }
        
        // 温度范围检查 (-50°C 到 80°C)
        if (data.getTemperature() < -50.0 || data.getTemperature() > 80.0) {
            logger.warn("温度值超出合理范围: {}", data.getTemperature());
            return false;
        }
        
        // 湿度范围检查 (0% 到 100%)
        if (data.getHumidity() < 0.0 || data.getHumidity() > 100.0) {
            logger.warn("湿度值超出合理范围: {}", data.getHumidity());
            return false;
        }
        
        return true;
    }
}